
package com.ld.security.server.admin.modules.ge.view;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ld.security.auth.shiro.anno.IgnoreUserToken;
import com.ld.security.common.core.exception.ApiException;
import com.ld.security.common.core.util.JsonUtil;
import com.ld.security.common.core.util.ReflectionUtil;
import com.ld.security.common.core.util.ScriptUtil;
import com.ld.security.common.core.util.UuidUtil;
import com.ld.security.common.mybatis.base.mapping.SqlMapping;
import com.ld.security.common.mybatis.base.po.IdPo;
import com.ld.security.common.mybatis.base.vo.DataVo;
import com.ld.security.common.mybatis.constant.FieldTypeConstant;
import com.ld.security.common.mybatis.util.JdbcUtil;

import com.ld.security.common.tomcat.anno.AjaxLogKey;
import com.ld.security.common.tomcat.util.RespUtil;
import com.ld.security.common.tomcat.util.SessionUtil;
import com.ld.security.server.admin.modules.ge.entity.GeEarlyModelEntity;
import com.ld.security.server.admin.modules.ge.entity.GeFieldEntity;
import com.ld.security.server.admin.modules.ge.po.DynModelPo;
import com.ld.security.server.admin.modules.ge.service.IGeEarlyModelService;
import com.ld.security.server.admin.modules.ge.service.IGeViewService;
import com.ld.security.server.admin.modules.ge.vo.EarlyDetailsVo;
import com.ld.security.server.admin.modules.ge.vo.ModelRenderVo;
import com.ld.security.server.admin.modules.ge.vo.RenderPageVo;
import com.ld.security.server.admin.modules.ge.vo.RenderViewVo;
import com.ld.security.server.admin.modules.ge.wrapper.DynWrapper;
import io.swagger.annotations.ApiOperation;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.util.*;
import java.util.stream.Collectors;


@Controller
@RequestMapping("/api/geProxy")
@Slf4j
public class GeProxyView {

    @Autowired
    IGeViewService iGeViewService;


    static List defList = new LinkedList();

    @ResponseBody
    @AjaxLogKey
    @IgnoreUserToken
    @ApiOperation("得到渲染视图")
    @RequestMapping(value = "/getRenderView", method = RequestMethod.POST)
    public DataVo getViewDetails(@Valid @RequestBody IdPo po) {
        RenderViewVo vo =  iGeViewService.getRenderView(po.getId());
        return  DataVo.of(vo);
    }


    @Autowired
    SqlMapping sqlMapping;

    @Autowired
    IGeEarlyModelService iGeEarlyModelService;
    @ResponseBody
    @AjaxLogKey
    @IgnoreUserToken
    @ApiOperation("执行分页查询")
    @RequestMapping(value = "/page", method = RequestMethod.POST)
    public DataVo<RenderPageVo> page(@Valid @RequestBody DynModelPo po) {
        RenderViewVo.ModelVo vo =po.getModelRender();
        //查询模型初始化
        //如果字段发现空，则判断初始化
        if(po.getModelRender() == null){
            RenderViewVo view =  iGeViewService.getRenderView(po.getViewId());
              for (RenderViewVo.ModelVo modelVo : view.getModelList()) {
                  if(modelVo.getCode().equals(po.getCode())){
                      vo = modelVo;
                      break;
                  }
              }
              po.setEarlyModels(view.getEarlyModels());
        }


        if(vo.getFields().isEmpty()){
            ApiException.throw400("字段不能为空");
        }

        String dataSourceId =  iGeViewService.getById(po.getViewId()).getDataSourceId();


        DynWrapper dynWrapper =  new DynWrapper(vo,po.getQuery());
        dynWrapper.setDataSource(dataSourceId);
        Page page =  po.toPage();

        RenderPageVo rp = new RenderPageVo();
        rp.setPageSql(dynWrapper.getSql());
        DataVo v =   DataVo.of(rp);

        try{
            sqlMapping.page(page,dynWrapper);
            rp.setTotal(page.getTotal());
            rp.setList(page.getRecords());
            rp.deleteNull();
            HashMap args =  new HashMap<>();

            //计算字段处理
          for (GeFieldEntity geFieldEntity : vo.getFields()) {
            if(geFieldEntity.getFieldType() != FieldTypeConstant.compute){
                continue;
            }
              for (Object o : rp.getList()) {
                  args.put("row",o);

                  Object val =  ScriptUtil.eval(geFieldEntity.getComputedFunc(),args);
                  ReflectionUtil.invokeSetter(o,geFieldEntity.getFieldName(),val);
              }
          }


        }catch (Exception e){
            rp.setList(defList);
            rp.setTotal(0);
            e.printStackTrace();
            v.setMessage("sql异常,清检查配置");
        }

        for (Object o : rp.getList()) {

            LinkedList checkList = new LinkedList<>();


              String modelId = vo.getId();
              for (EarlyDetailsVo.EarlyDetails earlyDetails : po.getEarlyModels()) {
                  GeEarlyModelEntity modelEntity =  earlyDetails.getEarlyModel();

                  if(modelEntity.getModelId().equals(modelId)){

                    boolean check =  earlyDetails.check(o);
                    CheckNode node = new CheckNode();
                    node.setCheck(check);
                    node.setEarlyModelId(modelEntity.getId());
                    node.setFieldName(modelEntity.getEarlyTarget());
                    //对指定字段设置检查结果

                      checkList.add(node);

                   // checkMap.put(earlyDetails.getEarlyModel().getEarlyTarget(),check);

                }
              }
              //模型设置检查结果
              ReflectionUtil.invokeSetter(o,"checkList",checkList);
        }

        return v;
    }

  @ApiOperation("文件下载")
  @RequestMapping(value = "/downExcel", method = RequestMethod.POST)
  public void downExcel(String json) {
      DynModelPo po = JsonUtil.toObject(json,DynModelPo.class);
      RenderPageVo<Map> vo = this.page(po).getData();

      List<Map> list = vo.getList().stream().map(v -> {
          Map<String,Object> map =  new LinkedHashMap<>();
          for (RenderViewVo.GeFieldCompVo geFieldCompVo : po.getModelRender().getFields()) {
              Object val =  ReflectionUtil.invokeGetter(v,geFieldCompVo.getFieldName());
              map.put(geFieldCompVo.getLabel(),val);
          }
          return map;
      }).collect(Collectors.toList());

      downExcel(list,po.getView().getLabel()+"_"+po.getModelRender().getLabel());
  }

  private void downExcel(List<Map> list,String id) {


            // 通过工具类创建writer
            ExcelWriter writer = ExcelUtil.getBigWriter();
            // 合并单元格后的标题行，使用默认标题样式
            //  writer.merge(row1.size() - 1, "一班成绩单");
            // 一次性写出内容，使用默认样式
            writer.write(list);

            // 关闭writer，释放内存

            RespUtil.downloadFile(writer,id+".xlsx");
      writer.close();

  }
        /**
         * 检查节点点
         */
    @Data
    private static class CheckNode{

        //预警模型编号
        private String earlyModelId;

        //预警字段
        private String fieldName;

        //预警结果
        private boolean check;

    }

}

